package com.adan.content.service.impl;

import com.adan.base.execption.XcPlusException;
import com.adan.content.mapper.TeachplanMapper;
import com.adan.content.model.dto.BindTeachplanMediaDto;
import com.adan.content.model.dto.TeachplanDto;
import com.adan.content.model.po.Teachplan;
import com.adan.content.model.po.TeachplanMedia;
import com.adan.content.service.TeachplanMediaService;
import com.adan.content.service.TeachplanService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 课程计划 服务实现类
 * </p>
 *
 * @author adan
 */
@Slf4j
@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan> implements TeachplanService {

    @Autowired
    private TeachplanMediaService teachplanMediaService;

    @Resource
    private TeachplanMapper teachplanMapper;

    @Override
    public List<TeachplanDto> queryTeachPlanTreeNode(Long courseId) {
        return teachplanMapper.selectTreeNodes(courseId);
    }

    @Override
    @Transactional
    public void saveTeachplan(Teachplan teachplan) {
        Long teachplanId = teachplan.getId();
        if (teachplanId == null){
            //添加课程计划
            Teachplan plan = new Teachplan();
            BeanUtils.copyProperties(teachplan, plan);
            //设置创建时间
            plan.setCreateDate(LocalDateTime.now());
            //设置排序
            plan.setOrderby(getTeachplanCount(teachplan.getCourseId(), teachplan.getParentid()));
            //保存数据
            boolean save = this.save(plan);
            if (!save){
                XcPlusException.cast("添加课程计划失败");
            }
            return;
        }
        //teachplanId课程计划id存在，则为更新操作
        Teachplan plan = new Teachplan();
        BeanUtils.copyProperties(teachplan, plan);
        plan.setChangeDate(LocalDateTime.now());
        boolean update = this.updateById(plan);
        if (!update){
            XcPlusException.cast("更新课程计划失败");
        }
    }

    @Override
    @Transactional
    public void deleteTeachplan(Long teachplanId) {
        if (teachplanId == null)
            XcPlusException.cast("课程计划id为空");
        // 1.删除课程计划
        Teachplan teachplan = this.getById(teachplanId);
        // 判断当前课程计划是章还是节
        Integer grade = teachplan.getGrade();
        if (grade == 1){
            // 当前课程计划为章
            // 查询当前课程计划下是否有小节
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            // select * from teachplan where parentid = {当前章计划id}
            queryWrapper.eq(Teachplan::getParentid, teachplan.getParentid());
            int count = this.count(queryWrapper);
            // 如果当前章下还有小节，则抛异常
            if (count > 0){
                XcPlusException.cast("课程计划信息还有子级信息，无法操作");
            }
            this.removeById(teachplanId);
        }else {
            // 课程计划为节
            this.removeById(teachplanId);
            // 2.删除课程计划关联的媒资信息
            LambdaQueryWrapper<TeachplanMedia> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TeachplanMedia::getTeachplanId, teachplanId);
            teachplanMediaService.remove(queryWrapper);
        }
    }

    @Override
    @Transactional
    public void orderByTeachplan(String moveType, Long teachplanId) {
        Teachplan teachplan = this.getById(teachplanId);
        Integer grade = teachplan.getGrade();   //层级
        // 章节移动是比较同一课程id下的orderby
        Long courseId = teachplan.getCourseId();
        // 章节移动是比较同一课程id下的orderby
        Long parentid = teachplan.getParentid();
        Integer orderby = teachplan.getOrderby();
        //构建查询条件
        LambdaQueryWrapper<Teachplan> lqw = new LambdaQueryWrapper<>();
        if ("moveup".equals(moveType)) {
           /* if (grade == 1){
               // 章节上移，找到上一个章节的orderby，然后与其交换orderby
               // SELECT * FROM teachplan WHERE
               // courseId = 117 AND grade = 1  AND orderby < 1 ORDER BY orderby DESC LIMIT 1
               LambdaQueryWrapper<Teachplan> lqw = new LambdaQueryWrapper<>();
               lqw.eq(Teachplan::getCourseId, courseId)
                       .eq(Teachplan::getGrade, grade)
                       .lt(Teachplan::getOrderby, orderby)
                       .orderByDesc(Teachplan::getOrderby)
                       .last("LIMIT 1");
               Teachplan plan = this.getOne(lqw);
               exchangeOrderby(teachplan, plan);
           } else if (grade == 2) {
               // 小节上移
               // SELECT * FROM teachplan WHERE
               // parentId = 268 AND orderby < 5 ORDER BY orderby DESC LIMIT 1
               LambdaQueryWrapper<Teachplan> lqw = new LambdaQueryWrapper<>();
               lqw.eq(Teachplan::getParentid, parentid)
                       .lt(Teachplan::getOrderby, orderby)
                       .orderByDesc(Teachplan::getOrderby)
                       .last("LIMIT 1");
               Teachplan plan = this.getOne(lqw);
               exchangeOrderby(teachplan, plan);
           } */
            //章节或者目录上移(只需要判断课程id和父节点id即可查询出响应的层级和节点)
            // SELECT * FROM teachplan WHERE
            // course_id = 117 AND parentId = 0 AND orderby < 5 ORDER BY orderby DESC LIMIT 1;

            lqw.eq(Teachplan::getCourseId, courseId)
                    // .eq(Teachplan::getGrade, grade)
                    .eq(Teachplan::getParentid, parentid)
                    .lt(Teachplan::getOrderby, orderby)
                    .orderByDesc(Teachplan::getOrderby)
                    .last("LIMIT 1");
            Teachplan plan = this.getOne(lqw);
            if (plan == null){
                XcPlusException.cast("已到顶部");
            }
            exchangeOrderby(teachplan, plan);
        }else if ("movedown".equals(moveType)){
            //章节或者目录上移
            // SELECT * FROM teachplan WHERE
            // course_id = 117 AND parentId = 268 AND orderby > 3 ORDER BY orderby asc LIMIT 1;
            lqw.eq(Teachplan::getCourseId, courseId)
                    .eq(Teachplan::getParentid, parentid)
                    .gt(Teachplan::getOrderby, orderby)
                    .orderByAsc(Teachplan::getOrderby)
                    .last("LIMIT 1");
            Teachplan plan = this.getOne(lqw);
            if (plan == null){
                XcPlusException.cast("已到底部");
            }
            exchangeOrderby(teachplan, plan);
        }

    }

    @Override
    @Transactional
    public void associationMedia(BindTeachplanMediaDto bindTeachplanMediaDto) {
        //教学计划id
        Long teachplanId = bindTeachplanMediaDto.getTeachplanId();
        Teachplan teachplan = this.getById(teachplanId);
        if (teachplan == null){
            XcPlusException.cast("教学计划不存在");
        }
        if (teachplan.getGrade() != 2){
            XcPlusException.cast("只允许第二级教学计划绑定媒资文件");
        }
        // 绑定媒资，如果之前已经绑定过了媒资，再次绑定时为更新
        // （例如该小节已经绑定了 星际牛仔.avi，现在改绑为 胶水.avi，其实现方式为先删再增）
        TeachplanMedia teachplanMedia = new TeachplanMedia();
        teachplanMedia.setTeachplanId(teachplanId);
        teachplanMedia.setMediaId(bindTeachplanMediaDto.getMediaId());
        teachplanMedia.setCourseId(teachplan.getCourseId());
        teachplanMedia.setMediaFilename(bindTeachplanMediaDto.getFileName());
        teachplanMedia.setCreateDate(LocalDateTime.now());
        LambdaQueryWrapper<TeachplanMedia> lqw = new LambdaQueryWrapper<TeachplanMedia>()
                .eq(TeachplanMedia::getTeachplanId, teachplanId);
        teachplanMediaService.saveOrUpdate(teachplanMedia, lqw);
    }


    @Override
    public void unAssociationMedia(Long teachPlanId, String mediaId) {
        LambdaQueryWrapper<TeachplanMedia> lqw = new LambdaQueryWrapper<>();
        lqw.eq(TeachplanMedia::getTeachplanId, teachPlanId)
                .eq(TeachplanMedia::getMediaId, mediaId);
        teachplanMediaService.remove(lqw);
    }

    /**
     * 交换两个课程计划排序字段
     * @param teachplan1 课程计划1
     * @param teachplan2 课程计划2
     */
    private void exchangeOrderby(Teachplan teachplan1, Teachplan teachplan2) {
        Integer order1 = teachplan1.getOrderby();
        Integer order2 = teachplan2.getOrderby();
        teachplan1.setOrderby(order2);
        teachplan2.setOrderby(order1);
        this.updateById(teachplan1);
        this.updateById(teachplan2);
    }

    /**
     * 获取最新的排序号
     * @param courseId 课程 id
     * @param parentId 父课程计划 i
     * @return int 最新排序号
     */
    private int getTeachplanCount(Long courseId, Long parentId){
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getCourseId, courseId);
        queryWrapper.eq(Teachplan::getParentid, parentId);
        return this.count(queryWrapper);
    }
}
